{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "<table>\n",
    " <tr align=left><td><img align=left src=\"./images/CC-BY.png\">\n",
    " <td>Text provided under a Creative Commons Attribution license, CC-BY. All code is made available under the FSF-approved MIT license. (c) Kyle T. Mandli</td>\n",
    "</table>\n",
    "\n",
    "Note:  This material largely follows the text \"Numerical Linear Algebra\" by Trefethen and Bau (SIAM, 1997) and is meant as a guide and supplement to the material presented there."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "from __future__ import print_function\n",
    "\n",
    "%matplotlib inline\n",
    "import numpy\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Gaussian Elimination\n",
    "\n",
    "Gaussian elimination is the process where one transforms a matrix or linear system through a series of operations into one that is at the very least upper triangular (it is often also presented as including the operation that transforms $A$ completely to diagonal).  These series of operations can be written as a sequence of successive matrix-matrix multiplications by lower triangular matrices.  Letting these matrices be $L_j$ and the resulting upper triangular matrix be $U$ we can write this as\n",
    "$$\n",
    "    \\overbrace{L_{m-1} \\cdots L_2 L_1}^{L^{-1}} A = U.\n",
    "$$\n",
    "Labeling the successive operations as $L^{-1}$ allows us to move $L$ to the other side of the equation and we see that in fact what we have done is computed another factorization of the matrix $A$ called the $LU$ factorization."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Example\n",
    "\n",
    "As an example of this process lets consider the matrix\n",
    "$$\n",
    "    A = \\begin{bmatrix}\n",
    "        2 & 1 & 1 & 0 \\\\\n",
    "        4 & 3 & 3 & 1 \\\\\n",
    "        8 & 7 & 9 & 5 \\\\\n",
    "        6 & 7 & 9 & 8\n",
    "    \\end{bmatrix}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "The first step is to remove the values in the first column below the diagonal, to do this we can multiply by the matrix\n",
    "$$\n",
    "    L_1 = \\begin{bmatrix}\n",
    "         1 &   &   &  \\\\\n",
    "        -2 & 1 &   &  \\\\\n",
    "        -4 &   & 1 &  \\\\\n",
    "        -3 &   &   & 1\n",
    "    \\end{bmatrix} \\text{ so that } L_1 A = \\begin{bmatrix}\n",
    "        2 & 1 & 1 & 0 \\\\\n",
    "          & 1 & 1 & 1 \\\\\n",
    "          & 3 & 5 & 5 \\\\\n",
    "          & 4 & 6 & 8\n",
    "    \\end{bmatrix}.\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "The next step is to remove the values below the diagonal of the second column.  This can be done with\n",
    "$$\n",
    "    L_2 = \\begin{bmatrix}\n",
    "         1 &    &   &   \\\\\n",
    "           &  1 &   &   \\\\\n",
    "           & -3 & 1 &   \\\\\n",
    "           & -4 &   & 1\n",
    "    \\end{bmatrix} \\text{ so that } L_2 L_1 A = \\begin{bmatrix}\n",
    "        2 & 1 & 1 & 0 \\\\\n",
    "          & 1 & 1 & 1 \\\\\n",
    "          &   & 2 & 2 \\\\\n",
    "          &   & 2 & 4\n",
    "    \\end{bmatrix}.\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Finally we multiply $A$ by $L_3$ defined as\n",
    "$$\n",
    "    L_3 = \\begin{bmatrix}\n",
    "         1 &   &    &   \\\\\n",
    "           & 1 &    &   \\\\\n",
    "           &   &  1 &   \\\\\n",
    "           &   & -1 & 1\n",
    "    \\end{bmatrix} \\text{ so that } L_3 L_2 L_1 A = \\begin{bmatrix}\n",
    "        2 & 1 & 1 & 0 \\\\\n",
    "          & 1 & 1 & 1 \\\\\n",
    "          &   & 2 & 2 \\\\\n",
    "          &   &   & 2\n",
    "    \\end{bmatrix}\n",
    "$$\n",
    "completing the factorization with\n",
    "$$\n",
    "    L^{-1} = L_3 L_2 L_1 = \\begin{bmatrix}\n",
    "         1 &   &    &   \\\\\n",
    "           & 1 &    &   \\\\\n",
    "           &   &  1 &   \\\\\n",
    "           &   & -1 & 1\n",
    "    \\end{bmatrix}\n",
    "    \\begin{bmatrix}\n",
    "         1 &    &   &   \\\\\n",
    "           &  1 &   &   \\\\\n",
    "           & -3 & 1 &   \\\\\n",
    "           & -4 &   & 1\n",
    "    \\end{bmatrix} \n",
    "    \\begin{bmatrix}\n",
    "         1 &   &   &   \\\\\n",
    "        -2 & 1 &   &   \\\\\n",
    "        -4 &   & 1 &   \\\\\n",
    "        -3 &   &   & 1\n",
    "    \\end{bmatrix}\n",
    "$$ \n",
    "and\n",
    "$$\n",
    "    U = \\begin{bmatrix}\n",
    "        2 & 1 & 1 & 0 \\\\\n",
    "          & 1 & 1 & 1 \\\\\n",
    "          &   & 2 & 2 \\\\\n",
    "          &   &   & 2\n",
    "    \\end{bmatrix}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "We can actually easily invert $L$ and finally can write $A$ as\n",
    "$$\n",
    "    A =\n",
    "    \\begin{bmatrix}\n",
    "         1 &   &   &   \\\\\n",
    "         2 & 1 &   &   \\\\\n",
    "         4 & 3 & 1 &   \\\\\n",
    "         3 & 4 & 1 & 1\n",
    "    \\end{bmatrix}\\begin{bmatrix}\n",
    "        2 & 1 & 1 & 0 \\\\\n",
    "          & 1 & 1 & 1 \\\\\n",
    "          &   & 2 & 2 \\\\\n",
    "          &   &   & 2\n",
    "    \\end{bmatrix}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Pivoting\n",
    "\n",
    "As you may recall from your linear algebra course pivoting of the rows and columns of $A$ is often an important addition to Gaussian elimination to ensure that we can in fact factorize the matrix.  As a simple example take the matrix\n",
    "$$\n",
    "    A = \\begin{bmatrix} 0 & 1 \\\\ 1 & 1 \\end{bmatrix}.\n",
    "$$\n",
    "Without switch the rows Gaussian elimination would fail at the first step!  This is made more hazardous if we consider the matrix\n",
    "$$\n",
    "    A = \\begin{bmatrix} 10^{-17} & 1 \\\\ 1 & 1 \\end{bmatrix}.\n",
    "$$\n",
    "on a finite precision machine.  In principle any row and column can be **pivoted** so that at each step we have the maximum value being used (on the diagonal) to perform the operations that compose the matrices $L_j$.  In practice however we restrict ourselves to only pivoting rows of the matrix (called partial pivoting)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Consider again the example from above and switch the 1st and 3rd rows using the criteria that we always want to use the largest value to do perform the reduction.  Defining the first pivot matrix as\n",
    "$$\n",
    "    P_1 = \\begin{bmatrix}\n",
    "          &   & 1 &   \\\\\n",
    "          & 1 &   &   \\\\\n",
    "        1 &   &   &   \\\\\n",
    "          &   &   & 1\n",
    "    \\end{bmatrix} \\quad \\text{so that} \\quad\n",
    "    P_1 A = \\begin{bmatrix}\n",
    "        8 & 7 & 9 & 5 \\\\\n",
    "        4 & 3 & 3 & 1 \\\\\n",
    "        2 & 1 & 1 & 0 \\\\\n",
    "        6 & 7 & 9 & 8\n",
    "    \\end{bmatrix}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Now defining the first $L_1$ as\n",
    "$$\n",
    "    L_1 = \\begin{bmatrix}\n",
    "        1 &   &   &   \\\\\n",
    "        -\\frac{1}{2} & 1 &   &   \\\\\n",
    "        -\\frac{1}{4} &   & 1 &   \\\\\n",
    "        -\\frac{3}{4} &   &   & 1\n",
    "    \\end{bmatrix} \\quad \\text{so that} \\quad\n",
    "    L_1 P_1 A = \\begin{bmatrix}\n",
    "        8 & 7 & 9 & 5 \\\\\n",
    "          & -\\frac{1}{2} & -\\frac{3}{2} & -\\frac{3}{2} \\\\\n",
    "          & -\\frac{3}{4} & -\\frac{5}{4} & -\\frac{5}{4} \\\\\n",
    "          & \\frac{7}{4} & \\frac{9}{4} & \\frac{17}{4}\n",
    "    \\end{bmatrix}.\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Again examining the remaining values in column 2 the maximum value lies in row 4 so we want to interchange this with the second row (note that we do not want to move the first row as that will bring non-zero values into the first column below the diagonal).\n",
    "$$\n",
    "    P_2 = \\begin{bmatrix}\n",
    "        1 &   &   &   \\\\\n",
    "          &   &   & 1 \\\\\n",
    "          &   & 1 &   \\\\\n",
    "          & 1 &   &\n",
    "    \\end{bmatrix}  \\quad \\text{and} \\quad \n",
    "    L_2 = \\begin{bmatrix}\n",
    "        1 &   &   &   \\\\\n",
    "          & 1 &   &   \\\\\n",
    "          & \\frac{3}{7} & 1 &   \\\\\n",
    "          & \\frac{2}{7}  &   & 1\n",
    "    \\end{bmatrix}  \\quad  \\text{so that}  \\quad \n",
    "    L_2 P_2 L_1 P_1 A = \\begin{bmatrix}\n",
    "        8 &            7 &            9 &             5 \\\\\n",
    "          &  \\frac{7}{4} &  \\frac{9}{4} &  \\frac{17}{4} \\\\\n",
    "          &              & -\\frac{2}{7} &   \\frac{4}{7} \\\\\n",
    "          &              & -\\frac{6}{7} &  -\\frac{2}{7}\n",
    "    \\end{bmatrix}.\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Finally\n",
    "$$\n",
    "    P_3 = \\begin{bmatrix}\n",
    "        1 &   &   &   \\\\\n",
    "          & 1 &   &   \\\\\n",
    "          &   &   & 1 \\\\\n",
    "          &   & 1 &\n",
    "    \\end{bmatrix}  \\quad \\text{and} \\quad \n",
    "    L_3 = \\begin{bmatrix}\n",
    "        1 &   &   &   \\\\\n",
    "          & 1 &   &   \\\\\n",
    "          &   & 1 &   \\\\\n",
    "          &   & -\\frac{1}{3} & 1\n",
    "    \\end{bmatrix} \\quad \\text{so that} \\quad\n",
    "    L_3 P_3 L_2 P_2 L_1 P_1 A = \\begin{bmatrix}\n",
    "        8 &            7 &            9 &             5 \\\\\n",
    "          &  \\frac{7}{4} &  \\frac{9}{4} &  \\frac{17}{4} \\\\\n",
    "          &              & -\\frac{6}{7} &  -\\frac{2}{7} \\\\\n",
    "          &              &              &   \\frac{2}{3} \\\\\n",
    "    \\end{bmatrix}.\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### LU Factorization with Partial Pivoting\n",
    "\n",
    "Due to the nature of the pivot matrices we can disentangle them from the matrices $L_j$.  Right now we have\n",
    "$$\n",
    "    L_3 P_3 L_2 P_2 L_1 P_1 A = U\n",
    "$$\n",
    "where what we want is\n",
    "$$\n",
    "    (L'_3 L'_2 L'_1) P_3 P_2 P_1 A = U.\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "It turns out we can easily do this by\n",
    "$$\n",
    "    L'_3 = L_3, \\quad L'_2 = P_3 L_2 P_3^{-1}, \\quad \\text{and} \\quad L'_1 = P_3 P_2 L_1 P_2^{-1} P_3^{-1}.\n",
    "$$\n",
    "These new matrices $L'_j$ can easily be computed and it turns out that the $L'_j$ matrices have the same structure with the rows permuted accordingly."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "In general then the $LU$ factorization with partial pivoting of the above example can be written as\n",
    "$$\n",
    "    \\underbrace{\\begin{bmatrix}\n",
    "          &   & 1 &   \\\\\n",
    "          &   &   & 1 \\\\\n",
    "          & 1 &   &   \\\\\n",
    "        1 &   &   & \n",
    "    \\end{bmatrix}}_{P = P_3 P_2 P_1} \\underbrace{\\begin{bmatrix}\n",
    "        2 & 1 & 1 & 0 \\\\\n",
    "        4 & 3 & 3 & 1 \\\\\n",
    "        8 & 7 & 9 & 5 \\\\\n",
    "        6 & 7 & 9 & 8\n",
    "    \\end{bmatrix}}_{A} = \n",
    "    \\underbrace{\\begin{bmatrix}\n",
    "        1           &              &              &   \\\\\n",
    "        \\frac{3}{4} &            1 &              &   \\\\\n",
    "        \\frac{1}{2} & -\\frac{2}{7} &            1 &   \\\\\n",
    "        \\frac{1}{4} & -\\frac{3}{7} & \\frac{1}{3}  & 1 \\\\\n",
    "    \\end{bmatrix}}_{L}\n",
    "    \\underbrace{\\begin{bmatrix}\n",
    "        8 &            7 &            9 &             5 \\\\\n",
    "          &  \\frac{7}{4} &  \\frac{9}{4} &  \\frac{17}{4} \\\\\n",
    "          &              & -\\frac{6}{7} &  -\\frac{2}{7} \\\\\n",
    "          &              &              &   \\frac{2}{3} \\\\\n",
    "    \\end{bmatrix}}_{U}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "The algorithm for the general factorization with partial pivoting then can be written as\n",
    "```\n",
    "U = A\n",
    "L = I\n",
    "P = I\n",
    "for k = 1 to m - 1\n",
    "    Select i >= k to maximize |u_{i,k}|\n",
    "    U[k, k:m] <==> U[i, k:m]\n",
    "    L[k, 1:k-1] <==> L[i, 1:k-1]\n",
    "    P[k, :] <==> P[i, :]\n",
    "    for j = k + 1 to m\n",
    "        L[j, k] = U[j, k] / U[k, k]\n",
    "        U[j, k:m] = U[j, k:m] - L[j, k] * U[k, k:m]\n",
    "```\n",
    "where `<==>` represents swapping of the two rows indicated."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Solving $Ax = b$\n",
    "\n",
    "To complete our discussion lets consider the solution of the linear system $Ax = b$.  We now have a factorization of the matrix $PA = LU$ so that the new system is $LU x = b$ (note that pivoting is allowed as long as we also interchange the elements of $b$ via $P \\cdot b$).  We can do this in two steps:\n",
    "\n",
    "1. Compute the pivoted $LU$ factorization $PA = LU$.\n",
    "1. Compute the solution to $L y = P b$ using forward substitution.\n",
    "1. Compute the solution to $U x = y$ using backward substitution."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Forward Substitution\n",
    "\n",
    "For forward substitution we proceed from the first row and progress downwards through the matrix.  We can then consider the general $i$th row with\n",
    "$$\n",
    "    L_{i,1} y_1 + L_{i,2} y_2 + \\cdots + L_{i,i-1} y_{i-1} + y_i = b_i\n",
    "$$\n",
    "noting that we are using the fact that the matrix $L$ has 1 on its diagonal.  We can now solve for $y_i$ as\n",
    "$$\n",
    "    y_i = b_i - \\left( L_{i,1} y_1 + L_{i,2} y_2 + \\cdots + L_{i,i-1} y_{i-1} \\right ).\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### Backward Substitution\n",
    "\n",
    "Backwards substitution requires us to move from the last row of $U$ and move upwards.  We can consider again the general $i$th row with\n",
    "$$\n",
    "    U_{i,i} x_i + U_{i,i+1} x_{i+1} + \\ldots + U_{i,m-1} x_{m-1} + U_{i,m} x_m = y_i.\n",
    "$$\n",
    "We can now solve for $x_i$ as\n",
    "$$\n",
    "    x_i = \\frac{1}{U_{i,i}} \\left( y_i - ( U_{i,i+1} x_{i+1} + \\ldots + U_{i,m-1} x_{m-1} + U_{i,m} x_m) \\right )\n",
    "$$"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  },
  "latex_envs": {
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 0
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
